用nodejs实现项目监听、打包、自动发送压缩包或消息到企业微信

您所在的位置:网站首页 nodejs webpack 后端 用nodejs实现项目监听、打包、自动发送压缩包或消息到企业微信

用nodejs实现项目监听、打包、自动发送压缩包或消息到企业微信

2023-04-14 19:55| 来源: 网络整理| 查看: 265

前言 起因 2023年了,有的项目因为各种原因还是没有用上ci/cd🌝,所以还是传统项目打包完,自己手动压缩,然后上传企业微信,本文目的就是将这部分工作交给机器,平均每次打包能节约2分钟吧😁(因为经常忘记是不是打包完了,所以可能还要比2分钟长) 你可以获取到什么知识 企业微信发消息(文本消息,文件消息) 在nodejs里面上传文件,前端一般是点击上传按钮选择文件,然后走formData那一套,那nodejs怎么做呢,可以看一下下面的实现 nodejs里面将文件夹变成zip,监听文件变化 总需求

运行本项目A,在项目B打包完成后,A项目检测有没有已经压缩的zip,有就删除,重新压缩,压缩完成后,向企业微信(钉钉/飞书等支持webhook的工具都可以,本文以企业微信为例)发信息或者发送这个压缩包(个人建议还是发消息,压缩包只支持20M以下(压缩包大于20M可能要考虑优化了哈哈😃),并且要走企业微信上传,数据无价🙂)

初始化 本文就用到了两个包 axios 与 archiver axios 只是为了发请求,你可以用任何一种你用的熟练或者内置的情况下就用项目的请求库 archiver 是打包的库,compressing也可以不过我打包出来的zip总是在奇怪的位置,懂哥可以补充一下 其实也可以用 linux 命令 zip,不过这种就怕删库🙃,加上你要装 压缩工具(zip这种) 到你的命令行 yarn init -y / npm init -y // package.json { "scripts": { "start": "node index.js" } } // 装包 如果是内置到项目里面,这里建议加 -D,如果是想外置就随意 yarn add axios archiver -D 复制代码 公共部分 在企业微信群里面可以申请机器人,会有一个 webhook 地址就是下面这个 weixinUploadUrl ,自己把对应位置的 weixinApiKey 复制出来就行 按下面的格式就是我想 等 D:/workspace/front/dist 这个文件夹生成完的时候自动压缩成 dist.zip const fs = require('fs'); const path = require('path'); const archiver = require('archiver'); const axios = require('axios'); const FormData = require('form-data'); const sourceDir = 'D:/workspace/front'; // 监听的目录 const watchFileName = 'dist'; // 监听的文件夹名称 const zipFile = `dist.zip`; const weixinApiKey = '这是你的企业微信机器人 key'; // 企业微信机器人 机器人key const weixinUploadUrl = `https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=${weixinApiKey}&type=file`; 复制代码 监听 监听部分用node 自带的 fs.watch,内置这个js文件这一步不需要 外置麻烦就在这里,比如dist文件夹从生成,到里面文件完全生成完毕,我不知道里面所有文件什么时候完全生成完毕,所以开始复制时我直接延时一分钟再打包,当然如果有朋友能知道怎么优化我这边调一下最好 // 监听 dist 文件夹 部分 fs.watch(sourceDir, { recursive: true }, (event, filename) => { if (filename !== watchFileName !== 'rename') { return; } setTimeout(compress, 60 * 1000) // }); 复制代码 压缩 如果不想走企业微信上传那就注释下面提到的那一行,就发个消息通知自己,自己复制压缩包发给同事就行,相信就直接走企业微信上传,然后机器人帮你发这个zip到群里 // 【压缩部分】 async function compress() { const distPath = path.join(sourceDir, watchFileName); // 这里加了 .. 是回到上一层,开始用的时候发现打出来的zip跑到 dist文件夹里面去了这里做修正 // 有优化建议的可以提一提,优化一下 const distZipPath = path.join(distPath, '..', zipFile); // 判断是否有 dist 文件夹 if (!fs.existsSync(distPath)) { console.log( `[${new Date().toLocaleString()}]: 未检测到 ${watchFileName} 文件夹,不进行压缩` ); return; } const isDirEmpty = (() => { const dirItems = fs.readdirSync(distPath); return dirItems.length === 0; })(); if (isDirEmpty) { console.log( `[${new Date().toLocaleString()}]: ${watchFileName} 文件夹为空,不进行压缩` ); return; } // 判断文件是否存在,存在则删除 if (fs.existsSync(distZipPath)) { fs.unlinkSync(distZipPath); console.log(`已删除文件:${distZipPath}`); } const output = fs.createWriteStream(distZipPath); const archive = archiver('zip', { zlib: { level: 9 } }); output.on('close', async function () { console.log( `[${new Date().toLocaleString()}]: 压缩成功,共 ${archive.pointer()} 个字节` ); let media_id = ''; // 将打包完成的文件上传企业微信 【看这里 上文提到可以注释的这一行】 media_id = await uploadZip(distZipPath); // 发送企业微信 信息 sendWeixinMessage(media_id); }); archive.on('error', function (err) { console.error(`[${new Date().toLocaleString()}]: 压缩失败: ${err}`); }); archive.pipe(output); archive.glob('**/*.*', { cwd: distPath, dot: false, matchBase: false, }); archive.finalize(); } 复制代码 上传企业微信 不相信企业微信数据安全的可以忽略不用这一步 这也可以当作在node环境下上传文件的示例 // 【企业微信上传文件部分】 async function uploadZip(distZipPath) { // 发送文件到企业微信 const bufferData = fs.readFileSync(distZipPath); const formData = new FormData(); formData.append('media', bufferData, { filename: zipFile }); const config = { headers: { 'Content-Type': `multipart/form-data; boundary=${formData._boundary}`, }, }; try { const { data: { media_id }, } = await axios.post(weixinUploadUrl, formData, config); console.log( `[${new Date().toLocaleString()}]: 文件上传成功,media_id为 ${ media_id }` ); return media_id; } catch (err) { console.error(`[${new Date().toLocaleString()}]: 文件上传失败: ${err}`); } }; 复制代码 发送信息 // 【企业微信发送信息部分】 async function sendWeixinMessage(mediaId = null, message = '') { const messageUrl = `https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${weixinApiKey}`; const messageContent = message || `${zipFile}压缩完成`; if (mediaId) { // 这块是走了上传的情况,走了上传就会得到这个mediaId // 企业微信根据这个 mediaId找到你上传的文件,让机器人发 const requestBody = { msgtype: 'file', file: { media_id: mediaId, }, }; await axios.post(messageUrl, requestBody); } // 这块就是企业微信发消息最简单的部分 详细可以参考 申请机器人的那个文档 const messageBody = { msgtype: 'text', text: { content: messageContent, }, }; await axios.post(messageUrl, messageBody); console.log( `[${new Date().toLocaleString()}]: 已向企业微信发送消息:${messageContent}` ); } 复制代码 实现代码

index.js

const fs = require('fs'); const path = require('path'); const archiver = require('archiver'); const axios = require('axios'); const FormData = require('form-data'); // const sourceDir = 'D:/workspace/frontend'; // 监听的目录 const sourceDir = 'D:/workspace/江海证券/front'; // 监听的目录 const watchFileName = 'dist'; // 监听的文件夹名称 const zipFile = `dist.zip`; const weixinApiKey = '475e214e-8cb5-4c83-b360-670bcad2f282'; // 企业微信机器人 机器人1 key const weixinUploadUrl = `https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=${weixinApiKey}&type=file`; // 【企业微信发送信息部分】 async function sendWeixinMessage(mediaId = null, message = '') { const messageUrl = `https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${weixinApiKey}`; const messageContent = message || `${zipFile}压缩完成`; if (mediaId) { const requestBody = { msgtype: 'file', file: { media_id: mediaId, }, }; await axios.post(messageUrl, requestBody); } const messageBody = { msgtype: 'text', text: { content: messageContent, }, }; await axios.post(messageUrl, messageBody); console.log( `[${new Date().toLocaleString()}]: 已向企业微信发送消息:${messageContent}` ); } // 【压缩部分】 async function compress() { const distPath = path.join(sourceDir, watchFileName); const distZipPath = path.join(distPath, '..', zipFile); // 判断是否有 dist 文件夹 if (!fs.existsSync(distPath)) { console.log( `[${new Date().toLocaleString()}]: 未检测到 ${watchFileName} 文件夹,不进行压缩` ); return; } const isDirEmpty = (() => { const dirItems = fs.readdirSync(distPath); return dirItems.length === 0; })(); if (isDirEmpty) { console.log( `[${new Date().toLocaleString()}]: ${watchFileName} 文件夹为空,不进行压缩` ); return; } // 判断文件是否存在,存在则删除 if (fs.existsSync(distZipPath)) { fs.unlinkSync(distZipPath); console.log(`已删除文件:${distZipPath}`); } const output = fs.createWriteStream(distZipPath); const archive = archiver('zip', { zlib: { level: 9 } }); output.on('close', async function () { console.log( `[${new Date().toLocaleString()}]: 压缩成功,共 ${archive.pointer()} 个字节` ); let media_id = ''; // 将打包完成的文件上传企业微信 // media_id = await uploadZip(distZipPath); // 发送企业微信 信息 sendWeixinMessage(media_id); }); archive.on('error', function (err) { console.error(`[${new Date().toLocaleString()}]: 压缩失败: ${err}`); }); archive.pipe(output); archive.glob('**/*.*', { cwd: distPath, dot: false, matchBase: false, }); archive.finalize(); } // 【企业微信上传文件部分】 async function uploadZip(distZipPath) { // 发送文件到企业微信 const bufferData = fs.readFileSync(distZipPath); const formData = new FormData(); formData.append('media', bufferData, { filename: zipFile }); const config = { headers: { 'Content-Type': `multipart/form-data; boundary=${formData._boundary}`, }, }; try { const { data: { media_id }, } = await axios.post(weixinUploadUrl, formData, config); console.log( `[${new Date().toLocaleString()}]: 文件上传成功,media_id为 ${ media_id }` ); return media_id; } catch (err) { console.error(`[${new Date().toLocaleString()}]: 文件上传失败: ${err}`); } }; let timer = null; //【监听部分】 监听 dist 文件夹 部分 fs.watch(sourceDir, { recursive: true }, (event, filename) => { if (filename !== watchFileName && event !== 'rename') { return; } setTimeout(compress, 60 * 1000) // }); 复制代码 内置方案

外置的情况下,不能完全准确的实现项目打包完毕开始压缩,这一点可以通过把这个js文件内置项目里面,但是项目会多装一个archiver包,如果接受内置的话,方案应该是算比较完美的,并且可以去掉监听的部分,直接压缩,可以用 npm scripts 自带的钩子实现,大体逻辑如下

// package.json { "scripts": { "build": "xxx " // 项目打包代码 "postbuild": "node 文中的js代码" // postXXX 会在 XXX 执行完成后执行 } } 复制代码 优化空间与扩展 优化空间 外置的情况可以整一个对象,项目A 地址:wx key 这种,监听多个文件夹,不过并发啥的就更复杂了,理论不会有🤣,一般不会同时打包3个项目,3个项目同时打包完吧😆,交给有缘人优化 监听 dist 文件夹的内容完全生成完毕,目前没有准确监听手段除非内置js到项目 扩展 这文章主要抛砖引玉,企业微信/钉钉/飞书等机器人发消息一般都是用在服务器CI/CD上面,同时呢,这个类似的服务你可以运行在服务器上面,实现自动签到,每日提醒,每日天气等各种地方 感谢

感谢各位看到这里,第一次发文章,可能有点啰嗦,喜欢的可以帮我在对应的这个github点个star😁 github 附带 内置与外置版本 github.com/qinbuff/mov…



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3